using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Sedge.Core.Configuration;
using Sedge.Core.Globalization;
using Sedge.Core.Utils;

namespace Sedge.Core.App
{
	public class SuiteFinder
	{
		#region Private fields

		private static readonly string _thisFile = Branding.PropertyPrefix + "this.file";
		private static readonly string _thisFolder = Branding.PropertyPrefix + "this.folder";

		#endregion //Private fields

		public static Suite GetSuite(SuiteFinderOptions options)
		{
			if (String.IsNullOrEmpty(options.SuiteFile))
				return null;

			XmlDocument xmlDocument = OpenXml(options.SuiteFile);
			XmlNode suiteNode = XmlToSuite.GetSuiteNode(xmlDocument, false);

			if (suiteNode == null)
				RaiseIncorrectConfigFile(options.SuiteFile);

			Suite suite = XmlToSuite.CreateReportableObjectFromXml<Suite>(suiteNode, null, ThisProperties(options.SuiteFile));
			suite.RootFolder = options.RootFolder;

			XmlToSuite.ProcessScheduleNode(suite, suiteNode);
			XmlToSuite.ProcessReportNode(suite, suiteNode);
			XmlToSuite.ProcessApplicationsNode(suite, suiteNode, options.AppName);
			XmlToSuite.ProcessTransportNode(suite, suiteNode);
			if (XmlToSuite.ProcessSetupNode(suite, suiteNode))
			{
				ProcessPartialFiles(suite, options.AppName);
			}

			return suite;
		}

		private static void ProcessPartialFiles(Suite suite, string appName)
		{
			string searchFolder = suite.RootFolder ?? String.Empty;
			string suiteSearchPath = suite.SearchPath;
			if (!String.IsNullOrEmpty(suiteSearchPath))
			{
				searchFolder = suiteSearchPath;
			}

			string[] partFiles = SearchForSuite(searchFolder, true);
			foreach (string partFile in partFiles)
			{
				XmlDocument xmlDocument = OpenXml(partFile);
				XmlNode suitePartNode = XmlToSuite.GetSuiteNode(xmlDocument, true);

				if (XmlToSuite.GetSuiteNodeName(suitePartNode) == suite.Name)
				{
					XmlToSuite.ProcessPropertiesNode(suite, suitePartNode);
					XmlToSuite.ProcessApplicationsNode(suite, suitePartNode, appName);
				}
			}
		}

		private static XmlDocument OpenXml(string path)
		{
			XmlDocument xml = null;
			try
			{
				xml = new XmlDocument();
				xml.Load(path);
			}
			catch (Exception)
			{
				ErrorHandler.Error(Locale.Strings.EIncorrectFormat, path);
			}
			return xml;
		}

		private static void RaiseIncorrectConfigFile(string file)
		{
			ErrorHandler.Error(Locale.Strings.EIncorrectFormat, file);
		}

		private static IDictionary<string, string> ThisProperties(string path)
		{
			return new Dictionary<string, string>
			       	{
			       		{_thisFile, Services.FileSystem.Path.GetFullPath(path)},
			       		{_thisFolder, Services.FileSystem.Path.GetDirectoryName(Services.FileSystem.Path.GetFullPath(path))}
			       	};
		}

		public static string[] SearchForSuite(string path, bool allFolders)
		{
			string[] results = { };
			if (!String.IsNullOrEmpty(path))
			{
				try
				{
					string[] files = Services.FileSystem.Directory.GetFiles(path, String.Concat("*.", Branding.ConfigExt),
																							  allFolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
					if (files.Length != 0)
						results = files;
				}
				catch
				{
					ErrorHandler.Warning(Locale.Strings.WFolderNotFound, path);
				}
			}
			return results;
		}

	}
}
